package cn.ckx.coding.common.utils.http;

import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;

/**
 * 
 */
public class CustomerHttpClientBuild extends HttpClientBuilder {

    private CustomerHttpClientBuild(){}
    public static CustomerHttpClientBuild custom(){
        return new CustomerHttpClientBuild();
    }
    /**
     * 设置连接池（默认开启https）
     *
     * @param maxTotal					最大连接数
     * @param defaultMaxPerRoute	每个路由默认连接数
     * @return	返回当前对象
     */
    public CustomerHttpClientBuild pool(int maxTotal, int defaultMaxPerRoute){
        //设置连接池大小
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
        connManager.setMaxTotal(maxTotal);
        connManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
        return (CustomerHttpClientBuild) this.setConnectionManager(connManager);
    }

    
    /**
     * 重试（如果请求是幂等的，就再次尝试）
     *
     * @param tryTimes		重试次数
     * @return	返回当前对象
     */
    public CustomerHttpClientBuild retry(final int tryTimes){
        return retry(tryTimes, false);
    }

    /**
     * 重试（如果请求是幂等的，就再次尝试）
     *
     * @param tryTimes						重试次数
     * @param retryWhenInterruptedIO		连接拒绝时，是否重试
     * @return	返回当前对象
     */
    public CustomerHttpClientBuild retry(final int tryTimes, final boolean retryWhenInterruptedIO){
        // 请求重试处理
        HttpRequestRetryHandler httpRequestRetryHandler = (exception, executionCount, context) -> {
            // 如果已经重试了n次，就放弃
            if (executionCount >= tryTimes) {
                return false;
            }
            // 如果服务器丢掉了连接，那么就重试
            if (exception instanceof NoHttpResponseException) {
                return true;
            }
            // 不要重试SSL握手异常
            if (exception instanceof SSLHandshakeException) {
                return false;
            }
            // 超时
            if (exception instanceof InterruptedIOException) {
                //return false;
                return retryWhenInterruptedIO;
            }
            // 目标服务器不可达
            if (exception instanceof UnknownHostException) {
                return true;
            }
            // 连接被拒绝
            if (exception instanceof ConnectTimeoutException) {
                return false;
            }
            // SSL握手异常
            if (exception instanceof SSLException) {
                return false;
            }

            HttpClientContext clientContext = HttpClientContext .adapt(context);
            HttpRequest request = clientContext.getRequest();
            // 如果请求是幂等的，就再次尝试
            return !(request instanceof HttpEntityEnclosingRequest);
        };
        this.setRetryHandler(httpRequestRetryHandler);
        return this;
    }
    
}
